using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Health;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// Properties for application configuration information
/// </summary>
public class AppConfigInfo : ApplicationInfo
{
    private const string CcrTypeId = "1e1ccbfc-a55d-4d91-8940-fa2fbf73c195";
    private const string CcdTypeId = "9c48a2b8-952c-4f5a-935d-f3292326bf54";
    private const string BasicDemographicTypeId = "bf516a61-5252-4c28-a979-27f45f62f78d";
    private const string BasicThingTypeId = "3e730686-781f-4616-aa0d-817bba8eb141";
    /// <summary>
    /// Enumerations for Health Record Permissions
    /// </summary>
    public enum HealthRecordItemPermissionEnum
    {
        /// <summary>
        /// Do not use this permission type
        /// </summary>
        All = 0,
        
        Create = 1,
        
        Delete = 2,
        
        Read = 3,
        
        Update = 4
    }
    /// <summary>
    /// Enumerations for Health Vault methods
    /// </summary>
    public enum HealthVaultMethods
    {
        
        GetThings = 0,
        
        PutThings = 1,
        
        AddApplication = 2,
        
        GetApplication = 3
    }
    /// <summary>
    /// Enumeration for Health Record ThingType
    /// </summary>
    public enum HealthRecordItemType
    {
        /// <summary>
        /// Medication Health Record item
        /// </summary>
        Medication = 0,
        /// <summary>
        /// Lab Result Health Record item
        /// </summary>
        LabResult = 1,
        /// <summary>
        /// HL7 Continuity of Care Document record item
        /// </summary>
        HL7CCD = 2,
        /// <summary>
        /// Continuity of Care Record record item
        /// </summary>
        CCR = 3,
        /// <summary>
        /// Basic profile
        /// </summary>
        Basic = 4,
        /// <summary>
        /// Application specific information
        /// </summary>
        ApplicationSpecific = 5,
        /// <summary>
        /// Personal image record item
        /// </summary>
        PersonalImage = 6,
        /// <summary>
        /// File record item
        /// </summary>
        BasicDemographicInformation = 7
    }
    /// <summary>
    /// Application Name for the newly created AppId
    /// </summary>
    private String applicationName = string.Empty;

    /// <summary>
    /// List to hold Certificate Public Key (as byte array)
    /// </summary>
    IList<byte[]> ListArray = new List<byte[]>() as IList<byte[]>;
    /// <summary>
    /// List of Health Record items
    /// </summary>
    Collection<HealthRecordItemType> authCollection = new Collection<HealthRecordItemType>();
    /// <summary>
    /// List of authorization rule
    /// </summary>
    Collection<AuthorizationRule> authRuleCollection;
    /// <summary>
    /// Collection of health vault methods
    /// </summary>
    Collection<HealthVaultMethods> methodsColl;
    /// <summary>
    /// Reference to authorization rule
    /// </summary>
    AuthorizationRule authRule;

    private string privacyStatement = string.Empty;
    
    private string termsOfUse = string.Empty;
    /// <summary>
    /// Path to Certificate 
    /// </summary>
    private String CertificatePath = string.Empty;
    /// <summary>
    /// Authorization reason for new App Id
    /// </summary>
    private string authorizationReason = string.Empty;

    /// <summary>
    /// List of Authorization Set Definition
    /// </summary>
    List<AuthorizationSetDefinition> authSetDefColl = new List<AuthorizationSetDefinition>();


    /// <summary>
    /// Gets and Sets the value Application
    /// </summary>
    public String ApplicationName
    {
        get { return applicationName; }
        set { base.Name = applicationName; }
    }
    /// <summary>
    /// Gets and Sets the value of Authorization Set
    /// </summary>
    public Collection<HealthRecordItemType> AuthorizationSet
    {
        get { return authCollection; }
        set
        {
            authCollection = value;
            GetAuthorizationSet(authCollection);
        }
    }

    /// <summary>
    /// Gets or sets the Value of Description
    /// </summary>
    public new string Description
    {
        get { return base.Description; }
        set { base.Description = value; }
    }

    /// <summary>
    /// Gets aur set the value for authorization reason
    /// </summary>
    public new string AuthorizationReason
    {
        get { return base.AuthorizationReason; }
        set { base.AuthorizationReason = value; }
    }
    /// <summary>
    /// Gets the List of Authorization rule
    /// </summary>
    public new Collection<AuthorizationRule> OfflineBaseAuthorizations
    {
        get { return authRuleCollection; }
    }


    /// <summary>
    /// Get or sets the privacy statemtement
    /// </summary>
    public new string PrivacyStatement
    {
        get { return privacyStatement; }
        set
        {
            privacyStatement = value;
            base.PrivacyStatement = new ApplicationBinaryConfiguration
                (new MemoryStream(UTF8Encoding.Default.GetBytes(privacyStatement)),
                "text/html");
        }
    }

    /// <summary>
    /// Gets or set the Terms of use URL
    /// </summary>
    public new string TermsOfUse
    {
        get { return termsOfUse; }
        set
        {
            termsOfUse = value;
            base.TermsOfUse = new ApplicationBinaryConfiguration
                (new MemoryStream(UTF8Encoding.Default.GetBytes(termsOfUse)),
                "text/html");
        }
    }

    /// <summary>
    /// Gets or set the Action Url
    /// </summary>
    public new Uri ActionUrl
    {
        get { return base.ActionUrl; }
        set { base.ActionUrl = value; }
    }


    /// <summary>
    /// Reads the public key from certificate
    /// </summary>
    private void GetPublicKeyFromCert()
    {
        X509Certificate cert = new X509Certificate(this.CertificatePath);
        byte[] key = cert.GetRawCertData();
        base.PublicKeys.Add(key);
    }


    /// <summary>
    /// Gets the type id of thing type
    /// </summary>
    /// <param name="itemType">Health Record Item Type </param>
    /// <returns>Type Id</returns>
    public static Guid GetTypeId(HealthRecordItemType itemType)
    {
        Guid typeId = new Guid();
        switch (itemType)
        {
            case HealthRecordItemType.ApplicationSpecific:
                typeId = Microsoft.Health.ItemTypes.ApplicationSpecific.TypeId;
                break;
            case HealthRecordItemType.Basic:
                typeId = new Guid(BasicThingTypeId);
                break;
            case HealthRecordItemType.CCR:
                typeId = new Guid(CcrTypeId);
                break;
            case HealthRecordItemType.HL7CCD:
                typeId = new Guid(CcdTypeId);
                break;
            case HealthRecordItemType.LabResult:
                typeId = Microsoft.Health.ItemTypes.LabTestResults.TypeId;
                break;
            case HealthRecordItemType.Medication:
                typeId = Microsoft.Health.ItemTypes.Medication.TypeId;
                break;
            case HealthRecordItemType.PersonalImage:
                typeId = Microsoft.Health.ItemTypes.PersonalImage.TypeId;
                break;
            case HealthRecordItemType.BasicDemographicInformation:
                typeId = Microsoft.Health.ItemTypes.Basic.TypeId;
                break;
            default:
                break;
        }
        return typeId;
    }
    /// <summary>
    /// Creates the List of authorization set definition
    /// </summary>
    /// <param name="items">Health Record Item</param>
    private void GetAuthorizationSet(Collection<HealthRecordItemType> items)
    {
        foreach (HealthRecordItemType item in items)
        {
            switch (item)
            {
                case HealthRecordItemType.CCR:
                    authSetDefColl.Add(new TypeIdSetDefinition(new Guid(CcrTypeId)));
                    break;
                case HealthRecordItemType.HL7CCD:
                    authSetDefColl.Add(new TypeIdSetDefinition(new Guid(CcdTypeId)));
                    break;
                case HealthRecordItemType.BasicDemographicInformation:
                    authSetDefColl.Add(new TypeIdSetDefinition(new Guid(BasicDemographicTypeId)));
                    break;
                case HealthRecordItemType.ApplicationSpecific:
                    authSetDefColl.Add(new TypeIdSetDefinition(Microsoft.Health.ItemTypes.ApplicationSpecific.TypeId));
                    break;
                case HealthRecordItemType.Basic:
                    authSetDefColl.Add(new TypeIdSetDefinition(Microsoft.Health.ItemTypes.Basic.TypeId));
                    break;
                case HealthRecordItemType.LabResult:
                    authSetDefColl.Add(new TypeIdSetDefinition(Microsoft.Health.ItemTypes.LabTestResults.TypeId));
                    break;
                case HealthRecordItemType.Medication:
                    authSetDefColl.Add(new TypeIdSetDefinition(Microsoft.Health.ItemTypes.Medication.TypeId));
                    break;
                case HealthRecordItemType.PersonalImage:
                    authSetDefColl.Add(new TypeIdSetDefinition(Microsoft.Health.ItemTypes.PersonalImage.TypeId));
                    break;
                default:
                    break;
            }
        }
    }
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="certificatePath">Certificate file path</param>
    /// <param name="largeLogoStream">Large logo image as a stream</param>
    /// <param name="smallLogoStream">Small logo image as a stream. Can be Stream.Null</param>
    public AppConfigInfo(string certificatePath, Stream largeLogoStream, Stream smallLogoStream)
    {
        authSetDefColl = new List<AuthorizationSetDefinition>();
        authRuleCollection = new Collection<AuthorizationRule>();
        methodsColl = new Collection<HealthVaultMethods>();
        this.CertificatePath = certificatePath;
        if (largeLogoStream == Stream.Null)
        {
            throw new ArgumentException("Large Logo is required");
        }
        base.LargeLogo = new ApplicationBinaryConfiguration(largeLogoStream, "Image");
        if (smallLogoStream != Stream.Null)
        {
            base.SmallLogo = new ApplicationBinaryConfiguration(smallLogoStream, "Image");
        }
        GetPublicKeyFromCert();
    }

    /// <summary>
    /// Sets the authorization rule
    /// </summary>
    /// <param name="healthRecordPermissionEnum">Enum value of Health record permission</param>
    /// <param name="itemTypeId">Thing type id</param>
    public void SetAuthorization(HealthRecordItemPermissionEnum healthRecordPermissionEnum, Guid itemTypeId)
    {
        authSetDefColl = new List<AuthorizationSetDefinition>();
        authSetDefColl.Add(new TypeIdSetDefinition(itemTypeId));
        switch (healthRecordPermissionEnum)
        {
            case HealthRecordItemPermissionEnum.Create:
                authRule = new AuthorizationRule(HealthRecordItemPermissions.Create, authSetDefColl, new List<AuthorizationSetDefinition>());
                break;
            case HealthRecordItemPermissionEnum.Delete:
                authRule = new AuthorizationRule(HealthRecordItemPermissions.Delete, authSetDefColl, new List<AuthorizationSetDefinition>());
                break;
            case HealthRecordItemPermissionEnum.Read:
                authRule = new AuthorizationRule(HealthRecordItemPermissions.Read, authSetDefColl, new List<AuthorizationSetDefinition>());
                break;
            case HealthRecordItemPermissionEnum.Update:
                authRule = new AuthorizationRule(HealthRecordItemPermissions.Update, authSetDefColl, new List<AuthorizationSetDefinition>());
                break;
            default:
                authRule = new AuthorizationRule(HealthRecordItemPermissions.Create, authSetDefColl, new List<AuthorizationSetDefinition>());
                break;
        }
        OfflineBaseAuthorizations.Add(authRule);
    }
}